# -*- coding:utf-8 -*-
from sqlalchemy import Column, Integer, and_
from sqlalchemy import func
from sqlalchemy.orm import load_only
import json

__author__ = 'Methew'
from ._base import db


# 节点相对位置
class TreeNodePosition(object):
    LastChild = 0
    FirstChild = 1
    NextSibling = 2
    PreviousSibling = 3


# 节点关系
class TREE_NODE_RELATION(object):
    Self = 0
    Parent = 1
    Child = 2
    Siblings = 3
    Descendants = 4
    Ancestors = 5
    Diff_tree = 6
    Same_tree = 7
    Same_level = 8
    Unknow = 9


class TreeNodeOnlyOneRootException(Exception):
    u"""一棵树只能有一个根节点，可以通过指定不同的tree_id来创建一个新树"""
    pass


class TreeNodeNotFound(Exception):
    u"""节点不存在"""
    pass


class TreeNodeInvalidOperation(Exception):
    u""" 非法节点操作"""
    pass


class lr_tree_manager(object):
    def __init__(self, model_class=None, session=None):
        """
        :param model_class: 提供一个ORM类
        :param session: 提供数据会话对象，如果没有提供则使用户ORM的类方法session取得会话
        :return:
        """
        self.init(model_class, session)

    def init(self, model_class, session):
        self._model_class = model_class
        if session is None and hasattr(self._model_class, "session"):
            self._session = self._model_class.session
        else:
            self._session = session

    def get_nodes(self, tree_id=None, level=0):
        """
            返回指定tree_id的树
        :param tree_id: 树id，如果没有指定tree_id，则返加所有树
        :param level:限制层次,1：只返回根节点，2：返回第二级
        :return:
        """
        session = self._session
        cls = self._model_class
        if tree_id is None:
            if level == 0:
                return session.query(cls).order_by(self._get_tree_sort_key(), "tree_left").all()
            else:
                return session.query(cls).filter(cls.tree_level <= level).order_by(self._get_tree_sort_key(),
                                                                                   "tree_left").all()
        else:
            if level == 0:
                return session.query(cls).filter(cls.__dict__[cls.__tree_key__] == tree_id).order_by(
                    self._get_tree_sort_key(), "tree_left").all()
            else:
                return session.query(cls).filter(
                    and_(cls.__dict__[cls.__tree_key__] == tree_id, cls.tree_level <= level)).order_by(
                    self._get_tree_sort_key(), "tree_left").all()


class LRTree(db.Model):
    """
        为ORM Model增加树形存储功能
    """

    # 根据此列来区分不同的树
    # 例：__tree_key__="site",则说明将使用site column的值作为tree_id来标识不同的树
    # 如果为None，则由tree_id字段来区分不同的树,tree_id树需要自己指定
    #
    __tree_key__ = "tree_id"
    __tree_sort__ = "tree_id"  # 用来声明不同树之间如何排序，如="tree_id"，则根据tree_id字段值来进行树排序

    tree_id = db.Column(db.Integer, default=0)  # 用来标识节点是哪一棵树的,默认为零,如果指定__tree_key__为其他值时，则以__tree_key__字段什来标识树，该字段就没有用。
    tree_left = db.Column(db.Integer, default=0)
    tree_right = db.Column(db.Integer, default=0)
    tree_level = db.Column(db.Integer, default=0)
    is_valid = db.Column(db.Integer, default=1)

    # 返回树Key
    tree_key = property(lambda self: self.get_node_tree_id(self))
    # 以下是用来获取节点关联属性的方法
    is_root = property(lambda self: self.tree_left == 1)  # 是否顶层
    # next_sibling = property(lambda self: self.get_next_sibling(self)) # 下一个兄弟节点
    # previous_sibling = property(lambda self: self.get_previous_sibling(self)) # 上一个兄弟节点
    # siblings = property(lambda self: self.get_siblings(self)) # 取所有兄弟
    # children = property(lambda self: self.get_children(self)) # 取所有下级
    # parent = property(lambda self: self.get_parent(self)) # 取所有上级
    # ancestors = property(lambda self: self.get_ancestors(self))
    # ancestors_count = property(lambda self: self.get_ancestors_count(self))
    # descendants = property(lambda self: self.get_descendants(self))
    # descendants_count = property(lambda self: self.get_descendants_count(self))
